#ifndef __FIBER_H__
#define __FIBER_H__

#include<ucontext.h>   //协程
#include<memory>   // shared_ptr
#include"thread.h"


namespace sylar{
// enable_shared_from_this可以使用this智能指针，但是不能在栈上创建对象了
class Fiber:public std::enable_shared_from_this<Fiber>{
public:
    friend class Scheduler;
    using ptr = std::shared_ptr<Fiber>;

    enum State{
      INIT,     // 初始化状态
      HOLD,     // 暂停状态
      EXEC,     // 执行中状态
      TERM,     // 结束状态
      READY,    // 可执行状态
      EXCEP    // 异常状态
    };
private:
    // 不允许创建默认构造，作为每个线程的第一个协程，主协程私有构造
    Fiber();


public:
    Fiber(std::function<void()>cb, size_t stacksize=0, bool use_caller = false);
    ~Fiber();

    /// 协程出问题一个把状态和函数重置, 也可以节省内存的分配
    void reset(std::function<void()> cb);

    /// 切换到当前协程，开始执行
    void swapIn();
    /// 让出执行权，把当前协程切换到后台
    void swapOut();

    uint64_t getId() const { return m_id;}

    /**
     * @brief 将当前线程切换到执行状态
     * @pre 执行的为当前线程的主协程
     * 与swapIn功能一样
     */
    void call();

    void back();
 
public:
    static Fiber::ptr GetThis();
    /// 设置当前协程
    static void SetThis(Fiber* fiber);
    /// 协程切换到后台并且设置为Ready状态
    static void YieldToReady();
    /// 协程切换到后台，并且设置为Hold状态
    static void YieldToHold();

    /// 追踪，统计总协程数
    static uint64_t TotalFibers();

    static void MainFunc();
    static void CallerMainFunc(); 

    /**
    * @brief 获取当前协程的id
    */
    static uint64_t GetFiberId();

    State getState(){ return m_state;}
private:
    uint64_t m_id = 0;
    uint32_t m_stacksize = 0;
    State m_state = INIT;

    ucontext_t m_ctx;
    void* m_stack = nullptr;

    std::function<void()> m_cb;
};
}

#endif